/*
 * CAnimationRecord.cpp
 *
 *  Created on: 07.04.2012
 *      Author: caffeine
 */

#include "CAnimationRecord.h"
#include "CAnimation.h"


namespace lampe{
namespace animation{

CAnimationRecord::Event_obejct::Event_obejct(CAnimationRecord*s){
	self=s;
}

void CAnimationRecord::Event_obejct::OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode* node){
	self->OnAnimationEnd(node);
}

IAnimationCallback*CAnimationRecord::getListener(u32 index){
	return events[index];
}

u32 CAnimationRecord::getListenerCount(){
	return events.size();
}

void CAnimationRecord::addAnimationEndListener(IAnimationCallback*listener){
	for (u32 i=0;i<events.size();i++)
		if (events[i]==listener)
			return;
	events.push_back(listener);
}
void CAnimationRecord::removeAnimationEndListener(IAnimationCallback*listener){
	for (u32 i=0;i<events.size();i++)
		if (events[i]==listener){
			events.erase(events.begin()+i);
			return;
		}
}

void CAnimationRecord::OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode*node){
	for (u32 i=0;i<events.size();i++){
		events[i]->AnimationEnd(this,node);
	}
}

IAnimation*CAnimationRecord::getParent(){
	return parent;
}

s32 findChildJoin(irr::scene::ISkinnedMesh::SJoint*parent,lampe::String name){
    irr::core::stringc n(name.c_str());
	for (u32 i=0;i<parent->Children.size();i++)
        if (parent->Children[i]->Name==n)
			return i;
	return -1;
}

u32 CAnimationRecord::getLength(){
	return end-start;
}

void CAnimationRecord::setSpeed(f32 s){
	speed=s;
}

f32 CAnimationRecord::getSpeed(){
	return speed;
}

void CAnimationRecord::copyCAnimation(irr::scene::ISkinnedMesh::SJoint*from,irr::scene::ISkinnedMesh::SJoint*to,u32 add,irr::scene::ISkinnedMesh*mesh){
	for (u32 i=0;i<from->PositionKeys.size();i++){
		irr::scene::ISkinnedMesh::SPositionKey*pp=mesh->addPositionKey(to);
		pp->frame=from->PositionKeys[i].frame+add;
		pp->position=from->PositionKeys[i].position;
	}

	for (u32 i=0;i<from->RotationKeys.size();i++){
		irr::scene::ISkinnedMesh::SRotationKey*rr=mesh->addRotationKey(to);
		rr->frame=from->RotationKeys[i].frame+add;
		rr->rotation=from->RotationKeys[i].rotation;
	}

	for (u32 i=0;i<from->ScaleKeys.size();i++){
		irr::scene::ISkinnedMesh::SScaleKey*ss=mesh->addScaleKey(to);
		ss->frame=from->ScaleKeys[i].frame+add;
		ss->scale=from->ScaleKeys[i].scale;
	}
}

lampe::String CAnimationRecord::getName(){
	return name;
}

void CAnimationRecord::setName(String n){
	name=n;
}

void CAnimationRecord::useFor(irr::scene::IAnimatedMeshSceneNode*node){
	//model->useAnimationFrom(parent->getMesh());
	node->setFrameLoop(start,end);

	node->setAnimationSpeed(speed);
	node->setTransitionTime(transitionTime);
	node->setAnimationEndCallback(event);
	//node->setLoopMode(true);
}

CAnimationRecord::CAnimationRecord(u32 s,u32 e,String n,irr::scene::ISkinnedMesh*m,CAnimation*p){
	event=new Event_obejct(this);
	start=s;
	end=e;
	speed=30;
	transitionTime=0.2f;

	name=n;
	parent=p;
	parent->grab();
	m->grab();
	irr::core::array<irr::scene::ISkinnedMesh::SJoint*> & newJoints = parent->getMesh()->getAllJoints();
	irr::core::array<irr::scene::ISkinnedMesh::SJoint*> & oldJoints = m->getAllJoints();
	if (parent->getNeedCreateBone()){
    	for (u32 j=0;j<m->getAllJoints().size();++j){
        	irr::scene::ISkinnedMesh::SJoint *joint = parent->getMesh()->addJoint();
        	*joint = *(m->getAllJoints()[j]);
    }
	    for ( u32 i=0; i < newJoints.size(); ++i ){
	    	irr::scene::ISkinnedMesh::SJoint * joint = newJoints[i];
	        for ( u32 c=0; c < joint->Children.size(); ++c ){
	            for ( u32 k=0; k < oldJoints.size(); ++k ){
	                if ( joint->Children[c] == oldJoints[k] ){
	                    joint->Children[c] = newJoints[k];
	                    break;
	                }
	            }
	        }

	    }
	}
	for (u32 i=0;i<newJoints.size();i++){
		copyCAnimation(oldJoints[i],newJoints[i],s,parent->getMesh());
		//for (u32 j=0;j<)
	}
	m->drop();
}

CAnimationRecord::~CAnimationRecord(){
	for (u32 i=0;i<events.size();i++)
		events[i]->drop();
	events.clear();
	event->drop();
	parent->drop();
}


void CAnimationRecord::setTransitionTime(f32 time){
	transitionTime=time;
}

f32 CAnimationRecord::getTransitionTime(){
	return transitionTime;
}


}//namespace animation
}//namespace lampe
